#ifndef udMeshing_h__
#define udMeshing_h__

//! @file udMeshing.h
//! udCompare.h provides an interface to create meshes from Unlimited Detail models.

#include <stdint.h>
#include "udDLLExport.h"
#include "udError.h"

#ifdef __cplusplus
extern "C" {
#endif

  typedef enum udError (udCompareOnWriteMeshCallback)(const char *pOutputName, void *pData);
  typedef void (udCompareOnWriteMeshCleanup)(void **pData);

  //!
  //! @struct udMeshingBPAOptions
  //! Contains the options for the meshing algorithm
  //!
  struct udMeshingBPAOptions
  {
    // Inputs
    const char *pBaseModelPath;       //! The path to the UDS model to be meshed
    const char *pObjOutputPath;       //! The directory to which intermediate obj meshes generated by the BPA algorithm will be written to. Must not be NULL when running standalone BPA algorithm
    uint32_t writeOBJColours;         //! If not 0 write objs with vertex colours taken from their source points
    uint32_t writeSingleOBJ;          //! If not 0 writes the output as a single obj - this may cause a failure for large inputs due to high memory usage
    const char *pSingleObjName;       //! The name to give a single output obj, if writeSingleOBJ is set (NULL for UUID)
    uint32_t mergeLevels;             //! If set grid cubes are merged into larger OBJs when written - increasing this value by 1 will multiply the size of output OBJs by a factor of 8. This setting is overwritten if writeSingleOBJ is set
    double globalOffset[3];           //! apply a global offset to the vertices when writing an OBJ

    // Algorithm parameters
    double ballRadius;                //! The radius of the ball used in the BPA algorithm
    double gridSize;                  //! The maximum size of each cube to be processed independantly by the BPA algorithm
    uint32_t maxGridPointCount;       //! The maximum number of grid points in a grid, if exceeded in a grid cube the grid will be subdivided
    struct udGeometry *pGeometry;     //! The geometry filter to restrict the BPA algorithm to, NULL to process whole model

    struct
    {
      udCompareOnWriteMeshCallback *pCallback; //! callback to be run on each mesh written (one for each grid), may be NULL
      void *pData; //! data to be passed to pCallback, may be NULL
      udCompareOnWriteMeshCleanup *pCleanup; //! function to call on call on pData once all mesh grids are finished writing, may be NULL
    } onWriteMesh; 

    void *pReserved; //! For internal use
  };

  //!
  //! @struct udMeshingBPAStatus
  //! Stores the internal state of the meshing process
  //!
  struct udMeshingBPAStatus
  {
    uint64_t nGrids; //! The total number of grids to be processed
    uint64_t nCompleted; //! The total number of grids that have been processed
    uint64_t running; //! Indicates if the algorithm is running
  };

  //!
  //! Meshes a model using the BPA algorithm. 
  //!
  //! @param pContext The UD context to be used to compare the models.
  //! @param pOptions The parameters passed to the BPA algorithm
  //! @param pStatus Pointer to the struct to which write the algorithm progress. May be NULL
  //! @result A udError value based on the result of performing BPA on the input model.
  //! @note This function begins the meshing process to write to obj, the pObjOutputPath option must not be NULL
  //!
  UDSDKDLL_API enum udError udMeshing_BPAMesh(struct udContext *pContext, struct udMeshingBPAOptions *pOptions, struct udMeshingBPAStatus* pStatus);

  //!
  //! Cancels a BPA meshing job started with pOptions
  //!
  //! @param pOptions The parameters passed to the BPA algorithm
  //! @result A udError value based on the result of cancelling the job
  //!
  UDSDKDLL_API enum udError udMeshing_BPACancelMeshing(struct udMeshingBPAOptions *pOptions);

#ifdef __cplusplus
}
#endif

#endif // udMeshing_h__
